<template>
  <Row :gutter="10">
    <Col span="12">
      <panel title="Web Api接口调用" :enableToggle="false" :maxHeight="autoHeight">
        <Form ref="frmParams" :model="config" :label-width="130">
          <FormItem label="Host">
            <Row>
              <Col span="24">
                <Select v-model="config.host">
                  <Option v-for="item of config.hosts" :value="item.url">{{ item.name }}</Option>
                </Select>
              </Col>
            </Row>
          </FormItem>
          <FormItem label="Api">
            <Row>
              <Col span="24">
                <Select v-model="config.api">
                  <Option v-for="(item, index) of config.apis" :value="index">{{ item.name }} - {{ item.url }}</Option>
                </Select>
              </Col>
            </Row>
          </FormItem>
          <FormItem :key="index" :class="item.formItemClasses" v-for="(item, index) of request" :label="item.desc" :prop="item.name">
            <Tooltip v-if="!item.isNew" :content="item.desc + '为必填项！'" :disabled="!!item.value" placement="top-start" theme="dark">
              <Row>
                <Col span="9">
                  <Input v-model="item.name" readonly />
                </Col>
                <Col span="4">
                  <Input v-model="item.type" readonly />
                </Col>
                <template v-if="item.handler">
                  <Col span="11">
                    <Select v-model="item.value" :ref="item.handler" filterable clearable @click.native="getHandlerDatas(item)" @on-change="optionChanged(item)" @on-clear="optionsClear(item)">
                      <Option v-for="option of options[item.handler]" :value="option.value">{{ option.text }}</Option>
                    </Select>
                  </Col>
                </template>
                <template v-else>
                  <Col :span="item.ref ? 6 : 11">
                    <Input v-model="item.value" />
                  </Col>
                  <Col span="5" v-if="item.ref">
                    <Select v-model="item.value" filterable>
                      <Option v-for="option of config.defines[item.ref]" :value="option.value">{{ option.text }}</Option>
                    </Select>
                  </Col>
                </template>
              </Row>
            </Tooltip>
            <Row v-else>
              <Col span="9">
                <Input v-model="item.name" />
              </Col>
              <Col span="4">
                <Select v-model="item.type">
                  <Option v-for="p of requestTypes" :value="p">{{ p }}</Option>
                </Select>
              </Col>
              <Col span="9">
                <Input v-model="item.value" />
              </Col>
              <Col span="2">
                <Button size="small" @click="removeParam(index)" type="error" icon="md-remove" shape="circle"></Button>
              </Col>
            </Row>
          </FormItem>
          <FormItem v-if="config.api">
            <Col span="24" style="text-align:left;">
              <ButtonGroup size="small" shape="circle">
                <Button type="success" icon="md-add" @click="addParams">追加参数</Button>
                <Button type="info" icon="md-copy" @click="onCopy">从剪切板</Button>
              </ButtonGroup>
            </Col>
          </FormItem>
          <FormItem :label-width="0">
            <Col span="24" style="text-align:right;">
              <ButtonGroup shape="circle">
                <Button @click="search" type="primary" icon="ios-search">查询</Button>
                <Button type="success" icon="md-copy" :disabled="jsonData.code != 0" @click="onCopyResult">复制结果</Button>
              </ButtonGroup>
            </Col>
          </FormItem>
        </Form>
      </panel>
    </Col>
    <Col span="12" class="code">
      <json-view class="section clear" :max-height="autoHeight" :json="jsonData" />
    </Col>
  </Row>
</template>
<script>
import download from '../../libs/download';

export default {
  components: {
    'json-view': () => import('~/components/basic/JsonView.vue')
  },
  data() {
    return {
      config: {
        hosts: [],
        apis: []
      },
      request: [],
      jsonData: {},
      ruleValidate: {},
      conditions: '',
      options: {
        getProjects: [],
        getDepartments: [],
        getProcesses: [],
        getProcessGroups: []
      },
      autoHeight: 520
    };
  },
  computed: {
    apiDefine() {
      return this.config.apis[this.config.api];
    },
    apiParams() {
      let rs = [];

      if (this.config && this.config.apis) {
        rs = (this.config.apis[this.config.api] || { params: [] }).params;
      }

      return rs;
    },
    requestTypes() {
      return this.$store.state.requestTypes;
    }
  },
  watch: {
    apiParams(value) {
      this.request = value;

      if (this.request.length > 0) {
        this.ruleValidate = {};

        this.request.forEach(el => {
          if (el.required) {
            this.ruleValidate[el.name] = [
              {
                required: true,
                message: `${el.desc}不能为空！`,
                trigger: 'blur'
              }
            ];
          }
        });
      }
    },
    request: {
      handler: function(datas) {
        datas.forEach(item => {
          item.formItemClasses = [];
          item.validError = false;

          if (item.required) {
            item.formItemClasses.push('ivu-form-item-required');

            if (!item.value) {
              item.formItemClasses.push('ivu-form-item-error');

              item.validError = true;
            }
          }
        });
      },
      deep: true,
      immediate: false
    }
  },
  methods: {
    getConfigs() {
      this.$http.get('/api/iworkflow/webapi/configs/').then(res => {
        this.config = res;
        this.config.host = res.hosts[0].url;
      });
    },
    addParams() {
      let apiDefine = this.apiDefine;

      if (!apiDefine) {
        this.$Message.error('请先选择api！');

        return;
      }

      let index = this.request.filter(r => r.isNew).length;

      this.request.push({
        desc: `参数${index + 1}`,
        name: '',
        type: apiDefine.method == 'post' ? 'body' : 'query',
        value: '',
        isNew: true
      });
    },
    removeParam(index) {
      this.request.splice(index, 1);
    },
    search() {
      if (!this.config.host || this.config.api == undefined) {
        this.$Message.warning('请选择Host和WebApi！');

        return;
      }

      let self = this;
      let datas = this.request.filter(r => r.name);
      let valid = datas.filter(d => d.validError).length == 0;

      if (valid) {
        let requestData = { host: self.config.host, api: self.config.apis[self.config.api].url, data: datas };

        if (datas.find(d => (d.name || '').toLowerCase() == 'isexport' && d.type == 'query' && d.value == 'true')) {
          download.download(`/api/iworkflow/webapi/invoke`, requestData);

          return;
        }

        self.$http.post(`/api/iworkflow/webapi/invoke`, requestData).then(res => {
          if (res.success) {
            self.jsonData = res.result;

            return;
          }

          self.jsonData = res;
        });
      } else {
        self.$Message.error('请求参数未通过验证，请确认输入必填项！');
      }
    },
    onCopy() {
      let self = this;
      let datas = [];

      this.$Modal.confirm({
        width: 720,
        render: h =>
          h('Input', {
            props: {
              autofocus: true,
              type: 'textarea',
              rows: 6,
              placeholder: '请输入URL参数',
              autosize: { minRows: 8 }
            },
            on: {
              input: function(val) {
                self.conditions = val;
              }
            }
          }),
        onOk() {
          let params = self.conditions.split('?');
          let items = (params.length > 1 ? params[1] : params[0]).split('&');

          items.forEach(item => {
            if (item) {
              let keyValue = item.split('=');
              let exsits = self.request.find(d => d.name.toLowerCase() == keyValue[0].toLowerCase());

              if (exsits) {
                exsits.value = decodeURI(keyValue[1]);
              } else {
                self.request.push({
                  name: keyValue[0],
                  type: 'query',
                  value: decodeURI(keyValue[1]),
                  desc: keyValue[0],
                  isNew: true
                });
              }
            }
          });
        }
      });

      return;
    },
    onCopyResult() {
      this.$copyText(JSON.stringify(this.jsonData, null, 2)).then(() => {
        this.$Message.success('结果已复制！');
      });
    },
    optionChanged(item) {
      if (!item || !item.value) {
        return;
      }

      if (item.handler == 'getProcesses') {
        let processName = this.options.getProcesses.find(i => i.value == item.value).text;

        let pNames = processName.split('-');
        let extraParams = this.config.defines[pNames[pNames.length - 1].trim()];

        let items = this.request.filter(r => !r.extra);

        if (extraParams) {
          extraParams.forEach(el => {
            el.extra = true;

            //items.push(el);
          });
        }

        this.request = items;
      }

      if (item.handler == 'getProjects') {
        (this.request.find(c => c.name == 'ExProjectId') || {}).value = item.value;
      }

      if (item.handler == 'getDepartments') {
        (this.request.find(c => c.name == 'ExDepartmentId') || {}).value = item.value;
      }
    },
    optionsClear(item) {
      if (item.handler == 'getProjects') {
        this.options.getDepartments = [];
        this.options.getProcessGroups = [];
        this.options.getProcesses = [];

        this.$refs['getDepartments'][0].clearSingleSelect();
        this.$refs['getProcessGroups'][0].clearSingleSelect();
        this.$refs['getProcesses'][0].clearSingleSelect();
      }

      if (item.handler == 'getDepartments') {
        this.options.getProcessGroups = [];
        this.options.getProcesses = [];

        this.$refs['getProcessGroups'][0].clearSingleSelect();
        this.$refs['getProcesses'][0].clearSingleSelect();
      }

      if (item.handler == 'getProcessGroups') {
        this.options.getProcesses = [];

        this.$refs['getProcesses'][0].clearSingleSelect();
      }
    },
    getHandlerDatas(item) {
      if (this[item.handler] && typeof this[item.handler] == 'function') {
        this[item.handler](item);
      }
    },
    getProjects(item) {
      let requestData = { host: this.config.host, api: '/api/Project/GetAllProjectsForLeo', data: [] };

      this.$http.post(`/api/iworkflow/webapi/invoke`, requestData).then(res => {
        if (res.success) {
          let result = res.result.data.map(d => {
            return { text: `${d.ID}(${d.ProjectSN}) - ${d.ProjectName}`, value: d.ID };
          });

          this.options.getProjects = result;
          this.options.getDepartments = [];
          this.options.getProcessGroups = [];
          this.options.getProcesses = [];
        }
      });
    },
    getDepartments(item) {
      let projectId = this.request.find(r => r.name == 'ProjectID').value;

      if (!projectId) {
        this.$Message.warning('必须选择项目！');

        return;
      }

      let requestData = {
        host: this.config.host,
        api: '/api/Department/GetDepartmentIdName',
        data: [{ name: 'projectID', type: 'query', value: projectId }]
      };

      this.$http.post(`/api/iworkflow/webapi/invoke`, requestData).then(res => {
        if (res.success) {
          let result = res.result.data.map(d => {
            return {
              text: `${d.id} - ${d.DepartmentName}`,
              value: d.id
            };
          });

          this.options.getDepartments = result;
          this.options.getProcessGroups = [];
          this.options.getProcesses = [];
        }
      });
    },
    getProcessGroups(item) {
      let projectId = this.request.find(r => r.name == 'ProjectID').value;
      let departmentId = this.request.find(r => r.name == 'DepartmentID').value;
      let userId = this.request.find(r => r.name == 'applyUserID').value;

      if (!departmentId) {
        this.$Message.warning('必须选择部门！');

        return;
      }

      if (!userId) {
        this.$Message.warning('必须提供申请人ID！');

        return;
      }

      let requestData = {
        host: this.config.host,
        api: '/api/ProcessGroup/GetProcessGroupList',
        data: [
          { name: 'IsDisabled', type: 'query', value: false },
          { name: 'PageSize', type: 'query', value: 20000 }
        ]
      };

      this.$http.post(`/api/iworkflow/webapi/invoke`, requestData).then(res => {
        if (res.success) {
          let result = res.result.data.dataList.map(d => {
            return {
              text: d.GroupNameFormatted,
              value: d.ID,
              GroupCode: d.GroupCode
            };
          });

          this.options.getProcessGroups = result;
          this.options.getProcesses = [];
        }
      });
    },
    getProcesses(item) {
      let groupId = this.request.find(r => r.name == 'ProcessGroupID').value;

      if (!groupId) {
        this.$Message.warning('必须选择流程组！');

        return;
      }

      let group = this.options.getProcessGroups.find(c => c.value == groupId);

      let requestData = {
        host: this.config.host,
        api: '/api/Process/GetProcessListByGroupCode',
        data: [{ name: 'groupCode', type: 'query', value: group.GroupCode }]
      };

      this.$http.post(`/api/iworkflow/webapi/invoke`, requestData).then(res => {
        if (res.success) {
          let result = res.result.data.map(d => {
            return {
              text: `${d.ID} - ${d.WorkflowCNName}`,
              value: d.ID
            };
          });

          this.options.getProcesses = result;
        }
      });
    }
  },
  mounted() {
    this.getConfigs();
    this.$bus.on('windowResizeChanged', client => (this.autoHeight = client.height));
  }
};
</script>
<style lang="less" scoped>
.ivu-form-item {
  margin-bottom: 5px;
}

.config-split {
  margin-top: 15px;
  margin-bottom: 8px;
  padding-bottom: 5px;
  padding-left: 20px;
  font-weight: bold;
  font-style: italic;
  border-bottom: 1px dotted #ccc;
}

.code {
  font-size: 13px;
  margin-top: 0;
  margin-bottom: 0;
  border-radius: 5px;
  overflow: hidden;
}

.ivu-tooltip {
  width: 100%;
}
</style>
